﻿package MV_BMP// ActionScript file
{
	import flash.display.Bitmap;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	import flash.utils.Timer;
	
	/**
	 *由矢量动画转换而成的位图动画类 
	 * @author 葛增文
	 * 
	 */	
	public class MovieClip_BMP extends Sprite
	{
		private var _targetMc:MovieClip;/*目标MC*/
		private var _drawFrame:int;/*当前需要绘制的帧，为0表示全部绘制完成*/
		private var _cannotPlay:Boolean=false;/*无法播放标记*/
		
		private var _framesAry:Array;
		private var _currentFrame:int;
		private var _currentLabel:String;
		private var _isStop:Boolean;
		private var _singleFrameSign:Boolean=false;/*单帧图片*/
		public function MovieClip_BMP():void
		{
			this.addListener();
		}
		
		/**
		 *位图转换 
		 * @param target--目标MC
		 * @param excursionPoint--绘制偏移点
		 * @param drawRate--绘制频率（为-1表示动态绘制，为0代表一次性绘制，否则代表绘制两帧间的毫秒间隔数）
		 * 
		 */				
		public function turnFrom(target:MovieClip,excursionPoint:Point=null,drawRate:int=0):void
		{
			this.reset();
			this._targetMc=target;
			if(excursionPoint)
			{
				this.targetMc.x=-excursionPoint.x;
				this.targetMc.y=-excursionPoint.y;
			}
			this.drawFrame=1;
			if(!this.targetMc || this.targetMc.totalFrames<1)
			{
				throw new Error("对象剪辑为空或者不存在");
			}
			for(var i:int=0;i<targetMc.totalFrames;i++)
			{
				this.targetMc.gotoAndStop(i+1);
				var label:String=this.targetMc.currentLabel;
				this.framesAry.push({label:label,bmp:null,script:null});
			}
			if(this.targetMc.totalFrames==1)
			{
				this.singleFrameSign=true;
				this.drawFrameNow(this.drawFrame);
				var getBmp:DisplayObject_BMP=this.framesAry[0].bmp;
				this.addChild(getBmp);
			}
			else if(drawRate==0)
			{
				while(this.drawFrame<=this.targetMc.totalFrames)
				{
					this.drawFrameNow(this.drawFrame);
					this.drawFrame+=1;
				}
				this.currentFrame=1;
			}
			else if(drawRate>0)
			{
				this.cannotPlay=true;
				this.drawFrameNow(this.drawFrame);
				var drawTimer:Timer=new Timer(drawRate);
				drawTimer.addEventListener(TimerEvent.TIMER,drawByTimer);
				drawTimer.start();
			}
			this.stop();
		}
		
		/**
		 *时序绘制 
		 * @param e
		 * 
		 */		
		private function drawByTimer(e:TimerEvent):void
		{
			this.drawFrame+=1;
			this.drawFrameNow(this.drawFrame);
			if(this.drawFrame>=this.targetMc.totalFrames)
			{
				this.cannotPlay=false;
				var timer:Timer=(e.target as Timer);
				timer.stop();
				timer.removeEventListener(TimerEvent.TIMER,drawByTimer);
				timer=null;
				this.dispatchEvent(new BMPMCEvent(BMPMCEvent.TURNOVER,null,true));
			}
		}
		
		/**
		 *绘制某一帧 
		 * 
		 */		
		private function drawFrameNow(frame:int):void
		{
			this.targetMc.gotoAndStop(frame);
			var turnSprite:Sprite=new Sprite();
			turnSprite.addChild(targetMc);
			var bmp:DisplayObject_BMP=new DisplayObject_BMP(turnSprite);
			var label:String=this.targetMc.currentLabel;
			this.framesAry[frame-1].bmp=bmp;
		}
		
		/**
		 *添加监听 
		 * 
		 */		
		private function addListener():void
		{			
			this.addEventListener(Event.ADDED_TO_STAGE,updatePlayStatus);
			this.addEventListener(Event.REMOVED_FROM_STAGE,updatePlayStatus);
		}
		
		private function removeListener():void
		{
			this.removeEventListener(Event.ADDED_TO_STAGE,updatePlayStatus);
			this.removeEventListener(Event.REMOVED_FROM_STAGE,updatePlayStatus);
		}
		
		/**
		 *更新播放状态 
		 * 
		 */		
		private function updatePlayStatus(e:Event=null):void
		{
			if(!this.framesAry)
			{
				throw new Error("尚未导入动画");
			}
			if(this.singleFrameSign || this.cannotPlay)
			{
				return;
			}
			if(this.isStop || !this.stage)
			{
				this.removeEventListener(Event.ENTER_FRAME,enterFrameHandler);
			}
			else
			{
				this.addEventListener(Event.ENTER_FRAME,enterFrameHandler);
			}
		}
		
		
		/*模拟movieclip的方法*/
		public function play():void
		{
			this.isStop=false;
		}
		
		public function stop():void
		{
			this.isStop=true;
		}
		
		public function gotoAndPlay(frame:Object):void
		{
			var playFrame:int;
			if(frame is String)
			{
				playFrame=this.getFrameByLabel(frame as String);
				if(playFrame==-1)return;
			}
			else
			{
				playFrame=int(frame);
			}
			this.currentFrame=playFrame;
			this.play();
		}
		
		public function gotoAndStop(frame:Object):void
		{
			var playFrame:int;
			if(frame is String)
			{
				playFrame=this.getFrameByLabel(frame as String);
				if(playFrame==-1)return;
			}
			else
			{
				playFrame=int(frame);
			}
			this.currentFrame=playFrame;
			this.stop();
		}
		
		public function nextFrame():void
		{
			this.enterFrameHandler(null);
			this.stop();
		}
		
		public function prevFrame():void
		{
			if(this.currentFrame>0)
			{
				this.currentFrame-=1;
			}
			this.stop();
		}
		
		public function addFrameScript(...parameters):void
		{
			for(var i:int=0;i<parameters.length/2;i++)
			{
				var frame:int=parameters[i*2];
				var func:Function=parameters[i*2+1];
				if(frame<this.totalFrames)this.framesAry[frame].script=func;
			}
		}
		
		/**
		 *碰撞检测 
		 * @param checkObj
		 * @param checkObjBitmapDataPoint
		 * @return 
		 * 
		 */						
		public function hitTest(checkObj:Object,checkObjBitmapDataPoint:Point=null):Boolean
		{
			if(!this.stage || this.numChildren<1)return false;
			var testTarget:Bitmap=this.getChildAt(0) as Bitmap;
			var firstPoint:Point=testTarget.parent.localToGlobal(new Point(testTarget.x,testTarget.y));
			if(checkObj is Point)
			{
				return testTarget.bitmapData.hitTest(firstPoint,1,checkObj);
			}
			else if(checkObj is Rectangle && checkObjBitmapDataPoint)
			{
				return testTarget.bitmapData.hitTest(firstPoint,1,(checkObj as Rectangle),checkObjBitmapDataPoint)
			}
			return false;
		}
		
		/**
		 *克隆方法 
		 * @return 
		 * 
		 */		
		public function clone():MovieClip_BMP
		{
			if(this.cannotPlay)
			{
				throw new Error("动画尚未创建完成");
			}
			var returnMV:MovieClip_BMP=new MovieClip_BMP();
			returnMV._framesAry=new Array;
			for(var i:int=0;i<this.framesAry.length;i++)
			{
				var frameObj:Object=this.framesAry[i];
				var newBmp:DisplayObject_BMP=(frameObj.bmp as DisplayObject_BMP).clone();
				var newFrameObj:Object={label:frameObj.label,bmp:newBmp,script:frameObj.script};
				returnMV.framesAry.push(newFrameObj);
			}
			returnMV.targetMc=this.targetMc;
			returnMV.drawFrame=this.drawFrame;
			returnMV.singleFrameSign=this.singleFrameSign;
			returnMV.currentFrame=1;
			returnMV.stop();
			return returnMV;
		}
		
		/**
		 *根据帧标签放回帧数 
		 * @param label
		 * @return (如果找不到对应的帧数，返回-1)
		 * 
		 */		
		private function getFrameByLabel(label:String):int
		{
			for(var i:int=0;i<this.framesAry.length;i++)
			{
				var checkFrameObj:Object=this.framesAry[i];
				if(label==checkFrameObj.label)return (i+1);
			}
			return -1;
		}
		
		/**
		 *响应播放的事件
		 * @param e
		 * 
		 */		
		protected function enterFrameHandler(e:Event):void
		{
			if(this.currentFrame==this.totalFrames)
			{
				this.currentFrame=1;
			}
			else
			{
				this.currentFrame+=1;
			}
		}
		
		public function reset():void
		{
			while(this.numChildren)this.removeChildAt(0);
			this._framesAry=new Array;
			this._targetMc=null;
			this.stop();
		}
		
		/**
		 *释放 
		 * 
		 */		
		public function release():void
		{
			this.removeListener();
			if(this.parent)this.parent.removeChild(this);
			while(this.numChildren)this.removeChildAt(0);
			this._framesAry=null;
		}
		
		/**
		 *获取帧数组 
		 * @return 
		 * 
		 */		
		private function get framesAry():Array
		{
			return _framesAry;
		}
		
		/**
		 *获取&设定当前播放帧 
		 * @return 
		 * 
		 */		
		public function get currentFrame():int
		{
			return _currentFrame;
		}
		
		public function set currentFrame(value:int):void
		{
			if(value>1 && this.cannotPlay)
			{
				throw new Error("动画尚未创建完成");
			}
			if(value<=this.totalFrames && value>0)
			{
				_currentFrame = value;
				while(this.numChildren)this.removeChildAt(0);
				var nowFrameObj:Object=this.framesAry[this.currentFrame-1];
				var nowBmp:DisplayObject_BMP=nowFrameObj.bmp;
				if(!nowBmp)
				{
					this.drawFrameNow(value);
					nowBmp=this.framesAry[this.currentFrame-1].bmp;
				}
				this.addChild(nowBmp);
				this.currentLabel=nowFrameObj.label;
				if(nowFrameObj.script)
				{
					nowFrameObj.script(this);
				}
				if(this.currentFrame==this.totalFrames)
				{
					this.dispatchEvent(new BMPMCEvent(BMPMCEvent.LAST_FRAME,null,true));
				}
			}
		}
		
		/**
		 *获取总帧数
		 * @return 
		 * 
		 */		
		public function get totalFrames():int
		{
			return this.framesAry.length;
		}
		
		/**
		 *获取&设定播放标记 
		 * @param value
		 * 
		 */		
		public function set isStop(value:Boolean):void
		{
			_isStop = value;
			this.updatePlayStatus();
		}
		
		public function get isStop():Boolean
		{
			return _isStop;
		}
		
		/**
		 *获取&设定当前播放帧标签 
		 * @return (若没有,返回空)
		 * 
		 */		
		public function get currentLabel():String
		{
			return _currentLabel
		}
		
		public function set currentLabel(value:String):void
		{
			if(value!=this.currentLabel)
			{
				var foreLabel:String=this.currentLabel;
				this._currentLabel=value;
				this.dispatchEvent(new BMPMCEvent(BMPMCEvent.LABEL_CHANGE,{fore:foreLabel,now:this.currentLabel},true));
			}
		}

		/**
		 *单帧图片标签 
		 * @return 
		 * 
		 */		
		public function get singleFrameSign():Boolean
		{
			return _singleFrameSign;
		}

		public function set singleFrameSign(value:Boolean):void
		{
			_singleFrameSign = value;
		}

		public function get targetMc():MovieClip
		{
			return _targetMc;
		}

		public function set targetMc(value:MovieClip):void
		{
			_targetMc = value;
		}

		public function get drawFrame():int
		{
			return _drawFrame;
		}

		public function set drawFrame(value:int):void
		{
			_drawFrame = value;
		}

		public function get cannotPlay():Boolean
		{
			return _cannotPlay;
		}

		public function set cannotPlay(value:Boolean):void
		{
			_cannotPlay = value;
		}
		
		
	}
}